#include "CCmdOfficeGM.h"
#include "../mainctrl.h"
#include "../cmd/dataprepare.h"
#include "CCmdGMSendBatchGifts.h"

CT_REGISTER_ASYNCCMD(ID_MAIN_GM_OFFICE, CCmdOfficeGM);

int CCmdOfficeGM::Do(void* pData)
{
    CT_ASSERT(pData);

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_GM_OFFICE ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_GM_PLAYER, pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    _iSubCmd = stReq.sub_type();
    stAns.set_sub_type(_iSubCmd);

    _uiGID = 0;
    _iGIDIndex = 0;
    _stGidList.Clear();

    if (stReq.has_gid())
    {
        _uiGID = (unsigned int)stReq.gid();
    }
    else if (stReq.has_usertoken())
    {
        CTSizeString<USER_TOKEN_LEN> szUserToken;
        szUserToken.Set("%s", stReq.usertoken().c_str());
        int iIndex = pstMainCtrl->m_stUserTokenToGID.HashFind(szUserToken);
        if (iIndex >= 0)
        {
            _stGidList = pstMainCtrl->m_stUserTokenToGID[iIndex];
        }
    }
    else if (stReq.has_rolename())
    {
        CTSizeString<ROLENAME_LEN> szRoleName;
        szRoleName.Set("%s", stReq.rolename().c_str());

        CRolenameKey stRoleNameKey;
        stRoleNameKey.Init(szRoleName);
        
        int iIndex = pstMainCtrl->m_stRolenameHash.HashFind(stRoleNameKey);
        if (iIndex >= 0)
        {
            _uiGID = pstMainCtrl->m_stRolenameHash[iIndex];
        }
    }

    LogicDo(RET_OK);
    return RET_OK;
}

int CCmdOfficeGM::LogicDo(int iRet)
{
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    int iIndex = 0;
    bool bUpdateBaseInfo = false;

    switch (_iSubCmd)
    {
    case ID_GM_OFFICE_SUB_FREEZE_LOGIN: //以天为单位冻结玩家登录
    case ID_GM_OFFICE_SUB_FREEZE_SPEAK: //以天为单位冻结玩家发言
    case ID_GM_OFFICE_SUB_FREEZE_GOLD: //以天为单位冻结使用金币
    case ID_GM_OFFICE_SUB_FREEZE_SILVER: //以天为单位冻结使用银币
    case ID_GM_OFFICE_SUB_FREEZE_BAG_STORGE: //以天为单位冻结背包和仓库
        {
            PREPARE_PLAYER_BASE_INFO(this, _uiGID);
            ASSERT_PLAYER_PREPARED(_uiGID);
            
            iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGID);
            if (iIndex < 0)
            {
                CT_ERROR(("no base data user(%u)", _uiGID));
                return AnsClients(RET_SYSTEM_FAIL);
            }
            CPlayerBaseInfo& stPlayerBase =
                pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

            iRet = pstMainCtrl->m_stOfficeGMMgr.FreezeRole(stPlayerBase, stReq);
            bUpdateBaseInfo = true;
        }
        break;
    case ID_GM_OFFICE_SUB_UNFREEZE_LOGIN: //解冻玩家登录限制
    case ID_GM_OFFICE_SUB_UNFREEZE_SPEAK: //解冻玩家发言限制
    case ID_GM_OFFICE_SUB_UNFREEZE_GOLD: //解冻玩家使用金币限制
    case ID_GM_OFFICE_SUB_UNFREEZE_SILVER: //解冻玩家使用银币限制
    case ID_GM_OFFICE_SUB_UNFREEZE_BAG_STORGE: //解冻玩家背包和仓库限制
        {
            PREPARE_PLAYER_BASE_INFO(this, _uiGID);
            ASSERT_PLAYER_PREPARED(_uiGID);
            
            iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGID);
            if (iIndex < 0)
            {
                CT_ERROR(("no base data user(%u)", _uiGID));
                return AnsClients(RET_SYSTEM_FAIL);
            }
            CPlayerBaseInfo& stPlayerBase =
                pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

            iRet = pstMainCtrl->m_stOfficeGMMgr.UnFreezeRole(stPlayerBase,
                stReq);
            bUpdateBaseInfo = true;
        }
        break;
    case ID_GM_OFFICE_SUB_SEND_ROLE_GIFT: //发送礼包给玩家
        {
            PREPARE_PLAYER_BASE_INFO(this, _uiGID);
            ASSERT_PLAYER_PREPARED(_uiGID);
            
            iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGID);
            if (iIndex < 0)
            {
                CT_ERROR(("no base data user(%u)", _uiGID));
                return AnsClients(RET_SYSTEM_FAIL);
            }
            CPlayerBaseInfo& stPlayerBase =
                pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

            iRet = pstMainCtrl->m_stOfficeGMMgr.SendRoleGift(stPlayerBase,
                stReq);
            bUpdateBaseInfo = true;
        }
        break;
    case ID_GM_OFFICE_SUB_SEND_SYS_NOTICE: //发送系统公告
        {
            iRet = pstMainCtrl->m_stOfficeGMMgr.SendSysNotice(stReq);
        }
        break;
    case ID_GM_OFFICE_SUB_SYS_STOP_NOTICE: //系统停机维护
        {
            iRet = pstMainCtrl->m_stOfficeGMMgr.SysStopNotice(stReq);
        }
        break;
    case ID_GM_OFFICE_SUB_REPAIR_ROLE_HUNLI: //修复角色魂力数据
        {
            PREPARE_PLAYER_DETAIL_INFO(this, _uiGID);
            ASSERT_PLAYER_DETAIL_PREPARED(_uiGID);

            iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(_uiGID);
            if (iIndex < 0)
            {
                CT_ERROR(("ID_GM_PLAYER_SUB_PULL_ALL_EQUIP user(%u)", _uiGID));
                return AnsClients(RET_SYSTEM_FAIL);
            }
            CPlayerDetailInfo& stPlayerDetail =
                pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

            iIndex = pstMainCtrl->m_stClanMgr.GetClanIndex(
                stPlayerDetail._uiGID);
            if (iIndex < 0)
            {
                CT_ERROR(("gid = %u not in any Clan",stPlayerDetail._uiGID));
                break;
            }
            CClanEntry& stClanEntry =
                pstMainCtrl->m_stClanMgr._stClanEntryHash[iIndex];
            
            if (stPlayerDetail._stUserClan._uiClanId != stClanEntry._uiClanId)
            {
                stPlayerDetail._stUserClan._uiClanId = stClanEntry._uiClanId;
                pstMainCtrl->m_stRewardBackMgr.UpdateDetailToDB(stPlayerDetail);
            }
        }
        break;
    case ID_GM_OFFICE_SUB_PULL_ALL_EQUIP:
        {
            PREPARE_PLAYER_DETAIL_INFO(this, _uiGID);
            ASSERT_PLAYER_DETAIL_PREPARED(_uiGID);

            int iDetailIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(_uiGID);
            if (iDetailIndex < 0)
            {
                CT_ERROR(("ID_GM_PLAYER_SUB_PULL_ALL_EQUIP user(%u)", _uiGID));
                return AnsClients(RET_SYSTEM_FAIL);
            }
            CPlayerDetailInfo& stPlayerDetail = pstMainCtrl->m_stPlayerDetailInfoHash[iDetailIndex];

            CT_WARNING(("ID_GM_OFFICE_SUB_PULL_ALL_EQUIP %d %d", _uiGID, stPlayerDetail._stUserEquip._astEquipData.Size()));
        }
        break;
    case ID_GM_OFFICE_SUB_GET_SYS_DATA:
        {
            CTSizeString<MAX_BATTLE_NAME_BUFF> szSizeStr;
            szSizeStr.Cat("register: %d ",
                pstMainCtrl->m_stPlayerSnsCommInfoHash.Size(1));
            szSizeStr.Cat("online: %d ",
                pstMainCtrl->m_stPlayerOnline.GetOnlineCount());

            szSizeStr.Cat("open_regist: %d ",
                pstMainCtrl->m_stZoneOnlineData._stZoneData._chStopOpenRegist);
            szSizeStr.Cat("create_clan: %d ",
                pstMainCtrl->m_stZoneOnlineData._stZoneData._chStopCreateClan);

            stAns.add_str_data(szSizeStr());
        }
        break;
    case ID_GM_OFFICE_SUB_GET_ROLE_BY_GID: //通过GID获取角色信息
    case ID_GM_OFFICE_SUB_GET_ROLE_BY_ROLENAME: //通过昵称获取用户信息
        {
            PREPARE_PLAYER_BASE_INFO(this, _uiGID);
            ASSERT_PLAYER_PREPARED(_uiGID);

            PREPARE_PLAYER_DETAIL_INFO(this, _uiGID);
            ASSERT_PLAYER_DETAIL_PREPARED(_uiGID);

            PREPARE_PLAYER_SNS_DETAIL_INFO(this, _uiGID);
            ASSERT_PLAYER_SNS_DETAIL_PREPARED(_uiGID);

            iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGID);
            if (iIndex < 0)
            {
                return AnsClients(RET_SYS_ERROR);
            }
            CPlayerBaseInfo& stPlayerBaseInfo =
                pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

            iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(_uiGID);
            if (iIndex < 0)
            {
                return AnsClients(RET_SYS_ERROR);
            }
            CPlayerDetailInfo& stPlayerDetailInfo =
                pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

            iIndex = pstMainCtrl->m_stPlayerSnsDetailInfoHash.HashFind(_uiGID);
            if (iIndex < 0)
            {
                return AnsClients(RET_SYS_ERROR);
            }
            CPlayerSnsDetailInfo& stPlayerSnsDetailInfo =
                pstMainCtrl->m_stPlayerSnsDetailInfoHash[iIndex];

            GetRoleInfo(stPlayerBaseInfo, stPlayerDetailInfo,
                stPlayerSnsDetailInfo);
        }
        break;

    case ID_GM_OFFICE_SUB_GET_ROLE_BY_USERTOKEN: //通过OPENID获取用户信息
        {
            for ( ; _iGIDIndex < _stGidList._auiGID.Size(); ++_iGIDIndex)
            {
                _uiGID = _stGidList._auiGID[_iGIDIndex];

                PREPARE_PLAYER_BASE_INFO(this, _uiGID);
                ASSERT_PLAYER_PREPARED(_uiGID);
                
                PREPARE_PLAYER_DETAIL_INFO(this, _uiGID);
                ASSERT_PLAYER_DETAIL_PREPARED(_uiGID);
                
                PREPARE_PLAYER_SNS_DETAIL_INFO(this, _uiGID);
                ASSERT_PLAYER_SNS_DETAIL_PREPARED(_uiGID);
                
                iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGID);
                if (iIndex < 0)
                {
                    continue;
                }
                CPlayerBaseInfo& stPlayerBaseInfo =
                    pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];
                
                iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(_uiGID);
                if (iIndex < 0)
                {
                    continue;
                }
                CPlayerDetailInfo& stPlayerDetailInfo =
                    pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];
                
                iIndex = pstMainCtrl->m_stPlayerSnsDetailInfoHash.HashFind(
                    _uiGID);
                if (iIndex < 0)
                {
                    continue;
                }
                CPlayerSnsDetailInfo& stPlayerSnsDetailInfo =
                    pstMainCtrl->m_stPlayerSnsDetailInfoHash[iIndex];
                
                GetRoleInfo(stPlayerBaseInfo, stPlayerDetailInfo,
                    stPlayerSnsDetailInfo);
            }
        }
        break;

    case ID_GM_OFFICE_SUB_SEND_BATCH_GIFTS:
        {
            CCmdGMSendBatchGifts* pstCmd =
                (CCmdGMSendBatchGifts*)CT_CMDFACTORY->CreateCmd(
                    ID_MAIN_INNER_GM_SEND_GIFT);
            if (!pstCmd)
            {
                CT_WARNING(("create CCmdGMSendBatchGifts error"));
                return AnsClients(RET_SYS_ERROR);
            }

            pstCmd->pstMainCtrl = pstMainCtrl;
            pstCmd->stReq = stReq;
            pstCmd->Do(NULL);
        }
        break;

    case ID_GM_OFFICE_SUB_SET_VIP_LEVEL: //设置VIP等级
        {
            PREPARE_PLAYER_BASE_INFO(this, _uiGID);
            ASSERT_PLAYER_PREPARED(_uiGID);
            
            iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGID);
            if (iIndex < 0)
            {
                CT_ERROR(("no base data user(%u)", _uiGID));
                return AnsClients(RET_SYSTEM_FAIL);
            }
            CPlayerBaseInfo& stPlayerBase =
                pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

            if (stReq.datas_size() <= 0)
            {
                return AnsClients(ERROR_OFFICE_GM_LESS_ARGUMENT);
            }
            
            char chNewVipLevel = (char)stReq.datas(0);
            if (chNewVipLevel <= stPlayerBase._chVipLevel ||
                    chNewVipLevel >= MAX_VIP_LEVEL)
            {
                return AnsClients(ERROR_OFFICE_GM_ERROR_ARGUMENT);
            }

            stPlayerBase._chVipLevel = chNewVipLevel;

            bUpdateBaseInfo = true;
        }
        break;

    case ID_GM_OFFICE_SUB_STOP_OPEN_REGIST: //设置服务器停止开放注册
        {
            if (stReq.datas_size() <= 0)
            {
                return AnsClients(ERROR_OFFICE_GM_LESS_ARGUMENT);
            }

            char chStopOpenRegist = (char)stReq.datas(0);
            
            CZoneData& stZoneData = pstMainCtrl->m_stZoneOnlineData._stZoneData;
            if (chStopOpenRegist > 0)
            {
                stZoneData._chStopOpenRegist = 1;
            }
            else
            {
                stZoneData._chStopOpenRegist = 0;
            }

            //保存数据
            CVarObjectKey stKey;
            stKey.m_chDataType = DT_ZONE_DATA;
            stKey.m_u64ID = stZoneData._uiZoneID;
            pstMainCtrl->UpdateData(stKey, stZoneData, VOP_UPDATE);
        }
        break;

    case ID_GM_OFFICE_SUB_STOP_CREATE_CLAN: //设置服务器停止创建家族
        {
            if (stReq.datas_size() <= 0)
            {
                return AnsClients(ERROR_OFFICE_GM_LESS_ARGUMENT);
            }

            char chStopCreateClan = (char)stReq.datas(0);
            
            CZoneData& stZoneData = pstMainCtrl->m_stZoneOnlineData._stZoneData;
            if (chStopCreateClan > 0)
            {
                stZoneData._chStopCreateClan = 1;
            }
            else
            {
                stZoneData._chStopCreateClan = 0;
            }

            //保存数据
            CVarObjectKey stKey;
            stKey.m_chDataType = DT_ZONE_DATA;
            stKey.m_u64ID = stZoneData._uiZoneID;
            pstMainCtrl->UpdateData(stKey, stZoneData, VOP_UPDATE);

        }
        break;
#if 0
    case ID_GM_OFFICE_SUB_RESET_ZONE_OPEN_TIME: //重置开服时间并重启
        {
            CZoneData& stZoneData = pstMainCtrl->m_stZoneOnlineData._stZoneData;
            stZoneData._iZoneOpenTime = time(NULL);

            //保存数据
            CVarObjectKey stKey;
            stKey.m_chDataType = DT_ZONE_DATA;
            stKey.m_u64ID = stZoneData._uiZoneID;
            pstMainCtrl->UpdateData(stKey, stZoneData, VOP_UPDATE);

            //退出
            pstMainCtrl->s_bExit = true;
        }
        break;
#endif
    case ID_GM_OFFICE_SUB_TRIGGER_BUY_GOODS: //外网模拟充值
        {
            PREPARE_PLAYER_BASE_INFO(this, _uiGID);
            ASSERT_PLAYER_PREPARED(_uiGID);

            PREPARE_PLAYER_DETAIL_INFO(this, _uiGID);
            ASSERT_PLAYER_DETAIL_PREPARED(_uiGID);

            iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGID);
            if (iIndex < 0)
            {
                return AnsClients(RET_SYS_ERROR);
            }
            CPlayerBaseInfo& stPlayerBase =
                pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

            iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(_uiGID);
            if (iIndex < 0)
            {
                return AnsClients(RET_SYS_ERROR);
            }
            CPlayerDetailInfo& stPlayerDetail =
                pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

            if (stReq.datas_size() <= 0)
            {
                return AnsClients(ERROR_OFFICE_GM_LESS_ARGUMENT);
            }

            int iID = 0;
            int iCount = 1;
            int iQcent = 0;

            if (stReq.datas_size() >= 1 && stReq.datas(0) > 0)
            {
                iID = stReq.datas(0);
            }

            if (stReq.datas_size() >= 2 && stReq.datas(1) > 0)
            {
                iCount = stReq.datas(1);
            }

            if (stReq.datas_size() >= 3 && stReq.datas(2) > 0)
            {
                iQcent = stReq.datas(2);
            }

            if (iID > 0)
            {
                pstMainCtrl->m_stActMgr.TriggerBuyGoods(
                    stPlayerDetail._stSplendidAct, stPlayerBase._uiGID, iID,
                    iCount, iQcent, stPlayerBase._stVipData._iPayGold);
            }
        }
        break;

    default:
        return AnsClients(ERROR_MAIN_SUB_CMD);
    }

    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    if (bUpdateBaseInfo) //保存数据 base info
    {
        iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGID);
        if (iIndex < 0)
        {
            CT_ERROR(("no base data user(%u)", _uiGID));
            return AnsClients(RET_SYSTEM_FAIL);
        }
        CPlayerBaseInfo& stPlayerBase =
            pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

        CVarObjectKey stKey;
        stKey.m_chDataType = DT_PLAYER_BASE_INFO;
        stKey.m_u64ID = _uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerBase, VOP_UPDATE);
    }

    return AnsClients(RET_OK);
}

int CCmdOfficeGM::AnsClients(int iRet)
{
    pstMainCtrl->m_stEncodeBuf.Clear();

    stMsgHead.set_msgret(iRet);

    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
    stMsgHead.set_msgret(iRet);
    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);

    if (pstMainCtrl->AnswerToClient(stEnpHead,pstMainCtrl->m_stEncodeBuf,true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    if (iRet == RET_OK && ID_GM_OFFICE_SUB_FREEZE_LOGIN == _iSubCmd)
    {
        pstMainCtrl->SetOfflineOnePlayer(_uiGID);
    }

    return Done(iRet);
}

void CCmdOfficeGM::GetRoleInfo(CPlayerBaseInfo& stPlayerBaseInfo,
        CPlayerDetailInfo& stPlayerDetailInfo,
        CPlayerSnsDetailInfo& stPlayerSnsDetailInfo)
{
    CTSizeString<MAX_BATTLE_NAME_BUFF> szSizeStr;
    
    szSizeStr.Cat("GID: %u ",stPlayerBaseInfo._uiGID);
    szSizeStr.Cat("Name: %s ",stPlayerBaseInfo._sRoleName());
    szSizeStr.Cat("OPENID: %s ",stPlayerBaseInfo._sUserToken());
    szSizeStr.Cat("Gold: %d ",stPlayerBaseInfo._iGold);
    szSizeStr.Cat("Silver: %lld ",stPlayerBaseInfo._i64Silver);
    szSizeStr.Cat("Romany: %d ",stPlayerBaseInfo._iRomany);
    szSizeStr.Cat("Fate: %d ",stPlayerBaseInfo._iFateForce);
    szSizeStr.Cat("Hunli: %d ",stPlayerBaseInfo._iHunli);
    szSizeStr.Cat("Spirit: %d ",stPlayerDetailInfo._stTreasureData._iSpirit);
    szSizeStr.Cat("Reputation: %d ",stPlayerDetailInfo._iReputation);
    szSizeStr.Cat("Lvl: %d ",stPlayerBaseInfo._shLevel);
    szSizeStr.Cat("Exp: %lld ",stPlayerBaseInfo._i64NowExp);
    szSizeStr.Cat("Academy: %d ",stPlayerBaseInfo._ucAcademy);
    szSizeStr.Cat("Vip: %d ",stPlayerBaseInfo._chVipLevel);
    szSizeStr.Cat("PotenLvl: %d ",stPlayerBaseInfo._ucCrystalPotenLevel);
    szSizeStr.Cat("PotenExp: %d ",stPlayerBaseInfo._iCrystalPotenExp);
    szSizeStr.Cat("Contribution: %d ",
        stPlayerSnsDetailInfo._stCommInfo._iContribution);
    
    stAns.add_str_data(szSizeStr());
}

